home *** CD-ROM | disk | FTP | other *** search
- /*
- File: New NewGWorld.c
-
- Contains: Sample application demonstrating the use of the new version of the NewGWorld routine
-
- Written by: ggs
-
- Copyright: Copyright (c) 1999 Apple Computer, Inc., All Rights Reserved.
-
- You may incorporate this Apple sample source code into your program(s) without
- restriction. This Apple sample source code has been provided "AS IS" and the
- responsibility for its operation is yours. You are not permitted to redistribute
- this Apple sample source code as "Apple sample source code" after having made
- changes. If you're going to re-distribute the source, we require that you make
- it clear in the source that the code was descended from Apple sample source
- code, but that you've made changes.
-
- Change History (most recent first):
- 08/2000 JM Carbonized, non-Carbon code is commented out
- for demonstration purposes.
-
- */
-
- #include "CarbonPrefix.h"
- // system includes ----------------------------------------------------------
-
- #include <MacMemory.h>
- #include <Events.h>
- #include <Fonts.h>
- #include <Windows.h>
- #include <TextEdit.h>
- #include <Dialogs.h>
- #include <Devices.h>
- #include <Sound.h>
- #include <SoundInput.h>
- #include <ToolUtils.h>
- #include <OSUtils.h>
- #include <LowMem.h>
- #include <Gestalt.h>
-
- #include <stdlib.h>
-
- // project includes ---------------------------------------------------------
-
-
-
- // statics/globals (internal only) ------------------------------------------
-
- // Menu defs
- enum
- {
- kMenuApple = 128,
- kMenuFile = 129,
-
- kAppleAbout = 1,
- kFileInVRAM = 1, // allocate buffer in VRAM
- kFileInAGP, // allocate buffer in AGP memory
- kFileInSystem, // allocate buffer in system memory
- kFileTest, // run blitting test
- kFileQuit // quit
- };
-
- enum
- {
- // Initial Window Constants
- kWindowHeight = 400, // "
- kWindowWidth = 500, // "
- kWindowOffset = 100 // "
- };
-
- enum
- {
- kNoWhere = 0, // where is the off screen
- kInVRAM,
- kInAGP,
- kInSystem
- };
-
- Boolean gDone = false; // is app done
- SInt32 gSleepTime = 60; // yield time
-
- WindowPtr gpWindow = NULL; // main window
- GWorldPtr gpGWOffScreen = NULL; // main window offscreen scratch
- short gwLocOffscreen = 0; // curretn offscreen location
-
- Boolean gNewNewGWorld = false; // can we allocate in VRAm or AGP memory?
-
-
- // functions Prototypes (internal/private) -----------------------------------
-
- // returns GDHandle that window resides on (most of it anyway)
- GDHandle GetWindowDevice (WindowPtr pWindow);
- // checks and allocates (if required) a new GWorld size of pWindow in memory type target; returns true if (re)allocated
- Boolean BuildOffscreen (GWorldPtr * ppGWorld, WindowPtr pWindow, short * target);
- // fills offscreen buffer with random bright color
- void FillOffscreen (GWorldPtr pGWorld);
- // checks offscreen and blits it to the front
- void BlitToWindow (GWorldPtr pGWorld, WindowPtr pWindow, short * pLocation);
- // checks buffer and then runs 200 iteration CopyBits test offscreen to on and reprots results
- void RunTest (void);
- // Forces offscreen allocation (if different than current) in memory type specified and sets menu flag
- void AllocBuffer (short target);
-
- // standard stuff
- void InitToolbox(void); // standard inits
- Boolean SetUp (void); // application setup
- void DoMenu (SInt32 menuResult); // menu event handler
- void DoKey (SInt8 theKey, SInt8 theCode); // key down handling
- void DoUpdate (WindowPtr pWindow); // draw from off screen to on and updates control postions on screen for events
- void DoEvent (void); // event handler
- void CleanUp (void); // clean ups after application
-
- // functions (internal/private) ---------------------------------------------
-
- // returns GDHandle that window resides on (most of it anyway)
-
- GDHandle GetWindowDevice (WindowPtr pWindow)
- {
- GrafPtr pgpSave;
- Rect rectWind, rectSect;
- long greatestArea, sectArea;
- GDHandle hgdNthDevice, hgdZoomOnThisDevice;
-
- GetPort (&pgpSave);
- //SetPort (pWindow);
- SetPortWindowPort (pWindow);
- //rectWind = pWindow->portRect;
- GetPortBounds(GetWindowPort(pWindow), &rectWind);
- LocalToGlobal ((Point*)& rectWind.top); // convert to global coordinates
- LocalToGlobal ((Point*)& rectWind.bottom);
- hgdNthDevice = GetDeviceList ();
- greatestArea = 0; // initialize to 0
- // check window against all gdRects in gDevice list and remember
- // which gdRect contains largest area of window}
- while (hgdNthDevice)
- {
- if (TestDeviceAttribute (hgdNthDevice, screenDevice))
- if (TestDeviceAttribute (hgdNthDevice, screenActive))
- {
- // The SectRect routine calculates the intersection
- // of the window rectangle and this gDevice
- // rectangle and returns TRUE if the rectangles intersect,
- // FALSE if they don't.
- SectRect(&rectWind, &(**hgdNthDevice).gdRect, &rectSect);
- // determine which screen holds greatest window area
- // first, calculate area of rectangle on current device
- sectArea = (long)(rectSect.right - rectSect.left) * (rectSect.bottom - rectSect.top);
- if ( sectArea > greatestArea )
- {
- greatestArea = sectArea; // set greatest area so far
- hgdZoomOnThisDevice = hgdNthDevice; // set zoom device
- }
- hgdNthDevice = GetNextDevice(hgdNthDevice);
- }
- } // of WHILE
- SetPort (pgpSave);
- return hgdZoomOnThisDevice;
- }
-
- // --------------------------------------------------------------------------
-
- // checks and allocates (if required) a new GWorld size of pWindow in memory type target; returns true if (re)allocated
- // Currently, this routine checks to see if the GWorld is NULL, the PixMap is NULL, the baseAddr is NULL, the GDevice of the PixMap
- // and the window do not match, and if the color depths are not the same. If any of the previous is true the GWorld is re-allocated.
-
- Boolean BuildOffscreen (GWorldPtr * ppGWorld, WindowPtr pWindow, short * location)
- {
- GDHandle hgdWindow = GetWindowDevice (pWindow); // window GDevice
- //short wPixDepth = (**((CGrafPtr)pWindow)->portPixMap).pixelSize; // window pixel depth
- short wPixDepth = (**(GetPortPixMap(GetWindowPort(pWindow)))).pixelSize;
- Boolean fMustRebuild = false;
- Rect tempRect1;
-
- if (NULL == *ppGWorld) // if GWorld passed in is not allocated
- fMustRebuild = true;
- else
- {
- PixMapHandle hPixmap = GetGWorldPixMap (*ppGWorld);
- if ((NULL == hPixmap) || (NULL == GetPixBaseAddr (hPixmap))) // if pixmap handle is NULL or pixmap base address is NULL
- fMustRebuild = true;
- else if (GetGWorldDevice(*ppGWorld) != hgdWindow) // if GWorld not on same device as window
- fMustRebuild = true;
- else if ((**hPixmap).pixelSize != wPixDepth) // if color depths are not the same
- fMustRebuild = true;
- }
-
- if (fMustRebuild) // must rebuild
- {
- if (NULL != *ppGWorld) // if we have an allocated GWorld
- {
- DisposeGWorld (*ppGWorld); // dump our current GWorld
- *ppGWorld = NULL;
- }
- switch (*location) // where to we want to put it
- {
- case kInVRAM:
- //if (noErr == NewGWorld (ppGWorld, wPixDepth, &pWindow->portRect, NULL, hgdWindow, noNewDevice | useDistantHdwrMem))
- if (noErr == NewGWorld (ppGWorld, wPixDepth, GetPortBounds(GetWindowPort(pWindow), &tempRect1), NULL, hgdWindow, noNewDevice | useDistantHdwrMem))
- break;
- // we failed with VRAM, signal that and drop to AGP
- SysBeep (30);
- *location = kInAGP;
- case kInAGP:
- //if (noErr == NewGWorld (ppGWorld, wPixDepth, &pWindow->portRect, NULL, hgdWindow, noNewDevice | useLocalHdwrMem))
- if (noErr == NewGWorld (ppGWorld, wPixDepth, GetPortBounds(GetWindowPort(pWindow), &tempRect1), NULL, hgdWindow, noNewDevice | useLocalHdwrMem))
- break;
- // we failed with AGP, signal that and drop to system memory
- SysBeep (30);
- *location = kInSystem;
- case kInSystem:
- default:
- //if (noErr != NewGWorld (ppGWorld, wPixDepth, &pWindow->portRect, NULL, hgdWindow, noNewDevice | keepLocal))
- if (noErr != NewGWorld (ppGWorld, wPixDepth, GetPortBounds(GetWindowPort(pWindow), &tempRect1), NULL, hgdWindow, noNewDevice | keepLocal))
- {
- // we failed with system thus we can't allocate our GWorld, signal that, indicate no location and drop to debugger
- SysBeep (30);
- *location = kNoWhere;
- DebugStr ("\pUnable to allocate off screen image");
- return false; // nothing was allocated
- }
- }
- return true; // we rebuilt our GWorld
- }
- return false; // everything is okay
- }
-
- // --------------------------------------------------------------------------
-
- // fills offscreen buffer with random bright color
-
- void FillOffscreen (GWorldPtr pGWorld)
- {
- static RGBColor rgbColorOld;
- GDHandle hGDSave;
- CGrafPtr pCGrafSave;
- Rect rectSource /*= (pGWorld->portRect)*/;
- RGBColor rgbColor;
-
- GetPortBounds(pGWorld, &rectSource);
-
- do
- rgbColor.red = (Random () + 32767) / 2 + 32767;
- while (abs (rgbColor.red - rgbColorOld.red) < 3000);
- do
- rgbColor.green = (Random () + 32767) / 2 + 32767;
- while (abs (rgbColor.green - rgbColorOld.green) < 3000);
- do
- rgbColor.blue = (Random () + 32767) / 2 + 32767;
- while (abs (rgbColor.blue - rgbColorOld.blue) < 3000);
-
- rgbColorOld = rgbColor;
-
- GetGWorld (&pCGrafSave, &hGDSave);
- SetGWorld (pGWorld, NULL);
- if (LockPixels (GetGWorldPixMap (pGWorld)))
- {
- // draw some background
- EraseRect (&rectSource);
- RGBForeColor (&rgbColor);
- PaintRect (&rectSource);
- UnlockPixels (GetGWorldPixMap (pGWorld));
- }
- SetGWorld (pCGrafSave, hGDSave);
- }
-
- // --------------------------------------------------------------------------
-
- // checks offscreen and blits it to the front
-
- void BlitToWindow (GWorldPtr pGWorld, WindowPtr pWindow, short * pLocation)
- {
- Rect rectDest /*= ((GrafPtr)pWindow)->portRect*/;
- Rect rectSource /*= ((GrafPtr)pWindow)->portRect*/;
- GrafPtr pCGrafSave;
-
- GetPortBounds(GetWindowPort(pWindow), &rectDest);
- GetPortBounds(GetWindowPort(pWindow), &rectSource);
-
- // check to ensure we have a valid offscreen and rebuild if required
- if (BuildOffscreen (&pGWorld, pWindow, pLocation))
- FillOffscreen (pGWorld);
-
- // blit
- GetPort (&pCGrafSave);
- //SetPort ((GrafPtr) pWindow);
- SetPortWindowPort(pWindow);
- if (LockPixels (GetGWorldPixMap (pGWorld)))
- {
- //CopyBits (&((GrafPtr)pGWorld)->portBits, &pWindow->portBits, &rectSource, &rectDest, srcCopy, NULL);
- CopyBits ( GetPortBitMapForCopyBits(pGWorld), GetPortBitMapForCopyBits(GetWindowPort(pWindow)),
- &rectSource, &rectDest, srcCopy, NULL);
- UnlockPixels (GetGWorldPixMap (pGWorld));
- }
- else
- SysBeep (30);
- SetPort (pCGrafSave);
- }
-
- // --------------------------------------------------------------------------
-
- // checks buffer and then runs 200 iteration CopyBits test offscreen to on and reprots results
-
- void RunTest (void)
- {
- Str255 str = "\p";
- Rect rectDest /*= ((GrafPtr)gpWindow)->portRect*/;
- Rect rectSource /*= ((GrafPtr)gpWindow)->portRect*/;
- GrafPtr pCGrafSave;
- long time;
- short i;
-
- GetPortBounds(GetWindowPort(gpWindow), &rectDest);
- GetPortBounds(GetWindowPort(gpWindow), &rectSource);
-
- BlitToWindow (gpGWOffScreen, gpWindow, &gwLocOffscreen);
-
- GetPort (&pCGrafSave);
- //SetPort ((GrafPtr) gpWindow); //shouldn't this blow up in carbon?
- SetPortWindowPort(gpWindow);
- if (LockPixels (GetGWorldPixMap (gpGWOffScreen)))
- {
- time = TickCount ();
- for (i = 0; i < 200; i++)
- //CopyBits (&((GrafPtr)gpGWOffScreen)->portBits, &gpWindow->portBits, &rectSource, &rectDest, srcCopy, NULL);
- CopyBits (GetPortBitMapForCopyBits(gpGWOffScreen), GetPortBitMapForCopyBits(GetWindowPort(gpWindow)), &rectSource, &rectDest, srcCopy, NULL);
- time = TickCount () - time;
- time = 200 * 60 / time;
-
- NumToString (rectSource.right - rectSource.left, str);
- MoveTo (10, 20);
- DrawString (str);
- MoveTo (43, 20);
- DrawString ("\px");
- NumToString (rectSource.bottom - rectSource.top, str);
- MoveTo (56, 20);
- DrawString (str);
- NumToString (time, str);
- MoveTo (10, 35);
- DrawString (str);
- MoveTo (48, 35);
- DrawString ("\pfps");
- MoveTo (10, 50);
- switch (gwLocOffscreen)
- {
- case kInVRAM:
- DrawString ("\pIn VRAM");
- break;
- case kInAGP:
- DrawString ("\pIn AGP memory");
- break;
- case kInSystem:
- DrawString ("\pIn system memory");
- break;
- default:
- break;
- }
- UnlockPixels (GetGWorldPixMap (gpGWOffScreen));
- }
- else
- {
- SysBeep (30);
- MoveTo (10, 20);
- DrawString ("\pBlit test failed.");
- }
- SetPort (pCGrafSave);
- }
-
- // --------------------------------------------------------------------------
-
- // forces offscreen allocation (if different than current) in memory type specified and sets menu flag
-
- void AllocBuffer (short location)
- {
- MenuHandle hMenu;
- short i;
-
- // check to see if we are allocated in the desired buffer
- if (location != gwLocOffscreen)
- {
- // dispose to force a rebuild
- if (gpGWOffScreen)
- DisposeGWorld (gpGWOffScreen);
- gpGWOffScreen = NULL;
- gwLocOffscreen = location;
- }
- // ensure we are properly built
- if (BuildOffscreen (&gpGWOffScreen, gpWindow, &gwLocOffscreen))
- {
- FillOffscreen (gpGWOffScreen);
- BlitToWindow (gpGWOffScreen, gpWindow, &gwLocOffscreen);
- }
-
- // set menus
- hMenu = GetMenuHandle (kMenuFile);
- for (i = kFileInVRAM; i <= kFileInSystem; i++)
- CheckMenuItem (hMenu, i, false);
- CheckMenuItem (hMenu, gwLocOffscreen, true);
- }
-
- // --------------------------------------------------------------------------
-
- void InitToolbox()
- {
- MenuHandle menu;
-
- /*MaxApplZone ();
-
- InitGraf((Ptr) &qd.thePort);
- InitFonts();
- InitWindows();
- InitMenus();
- TEInit();
- InitDialogs(nil);*/
- InitCursor();
-
- //qd.randSeed = TickCount();
- SetQDGlobalsRandomSeed(TickCount());
-
- // Init Menus
- menu = NewMenu (kMenuApple, "\p\024"); // new apple menu
- InsertMenu (menu, 0); // add menu to end
- //AppendResMenu(menu, 'DRVR');
-
- menu = NewMenu (kMenuFile, "\pFile"); // new menu
- InsertMenu (menu, 0); // add menu to end
- AppendMenu (menu, "\pAllocate In VRAM;Allocate In AGP Memory;Allocate In System Memory;Run Blit Test;Quit/Q"); // add items
-
- DrawMenuBar();
- }
-
- // --------------------------------------------------------------------------
-
- Boolean SetUp (void)
- {
- Rect rectWindow;
- MenuHandle hMenu;
- long versionSystem;
- short i;
-
- InitToolbox ();
-
- SetRect (&rectWindow, 0, 0, kWindowWidth, kWindowHeight);
- OffsetRect (&rectWindow, kWindowOffset, kWindowOffset);
- gpWindow = NewCWindow (NULL, &rectWindow, "\pNew NewGWorld Test", true, kWindowGrowDocumentProc, (WindowPtr) -1, false, 0);
-
- gNewNewGWorld = false;
- // this will work 9.x
- Gestalt (gestaltSystemVersion, &versionSystem);
- if (0x00000900 <= (versionSystem & 0x00000FF00))
- gNewNewGWorld = true;
- else
- {
- // now it is tricky
- // we will try to allocate in VRAM and find out where the allocation really ended up.
- GWorldPtr pgwTest = NULL;
- Rect rectTest = {0, 0, 10, 10};
- //short wPixDepth = (**((CGrafPtr)gpWindow)->portPixMap).pixelSize; // window pixel depth
- short wPixDepth = (**(GetPortPixMap(GetWindowPort(gpWindow)))).pixelSize;
- GDHandle hgdWindow = GetWindowDevice (gpWindow); // window GDevice
- if ((noErr == NewGWorld (&pgwTest, wPixDepth, &rectTest, NULL, hgdWindow, noNewDevice | useDistantHdwrMem)) &&
- (pgwTest) /*&& // if we had a good allocation
- //(GetZone () != HandleZone ((Handle)((**pgwTest->portPixMap).baseAddr)))) // if we did not allocate in our zone
- (GetZone () != HandleZone ((Handle)((**(GetPortPixMap(pgwTest))).baseAddr)))*/)
- gNewNewGWorld = true;
- if (pgwTest)
- DisposeGWorld (pgwTest);
- }
- if (!gNewNewGWorld)
- {
- hMenu = GetMenuHandle (kMenuFile);
- for (i = kFileInVRAM; i <= kFileInAGP; i++)
- //DisableItem (hMenu, i);
- DisableMenuItem(hMenu, i);
- AllocBuffer (kInSystem);
- }
- else
- AllocBuffer (kInVRAM);
- return true;
- }
-
- // --------------------------------------------------------------------------
-
- void DoMenu (SInt32 menuResult)
- {
- SInt16 theMenu;
- SInt16 theItem;
- //Str255 daName;
- MenuRef theMenuHandle;
-
- theMenu = HiWord(menuResult);
- theItem = LoWord(menuResult);
- theMenuHandle = GetMenuHandle(theMenu);
-
- switch (theMenu)
- {
- case kMenuApple:
- switch (theItem)
- {
- case kAppleAbout:
- break;
- default:
- //OpenDeskAcc(daName);
- break;
- }
- break;
- case kMenuFile:
- switch (theItem)
- {
- case kFileInVRAM:
- AllocBuffer (kInVRAM);
- break;
- case kFileInAGP:
- AllocBuffer (kInAGP);
- break;
- case kFileInSystem:
- AllocBuffer (kInSystem);
- break;
- case kFileTest:
- RunTest ();
- break;
- case kFileQuit:
- gDone = true;
- break;
- }
- break;
- }
- HiliteMenu(0);
- DrawMenuBar();
- }
-
- // --------------------------------------------------------------------------
-
- void DoKey (SInt8 theKey, SInt8 theCode)
- {
- #pragma unused (theKey, theCode)
- }
-
- // --------------------------------------------------------------------------
-
- void DoUpdate (WindowPtr pWindow)
- {
- BlitToWindow (gpGWOffScreen, pWindow, &gwLocOffscreen);
- }
-
- // --------------------------------------------------------------------------
-
- void DoEvent (void)
- {
- EventRecord theEvent;
- Rect rectGrow;
- WindowRef whichWindow;
- long grow;
- SInt32 menuResult;
- SInt16 whatPart;
- SInt8 theKey;
- SInt8 theCode;
- RgnHandle rgnHandle = NewRgn();
- Rect tempRect1;
-
- if (WaitNextEvent(everyEvent, &theEvent, gSleepTime, NULL))
- {
- switch (theEvent.what)
- {
- case mouseDown:
- whatPart = FindWindow(theEvent.where, &whichWindow);
- switch (whatPart)
- {
- case inGoAway:
- break;
- case inMenuBar:
- DrawMenuBar();
- menuResult = MenuSelect(theEvent.where);
- if (HiWord(menuResult) != 0)
- DoMenu(menuResult);
- break;
- case inDrag:
- //DragWindow (whichWindow, theEvent.where, &(**LMGetGrayRgn()).rgnBBox);
- GetRegionBounds(GetGrayRgn(), &tempRect1);
- DragWindow (whichWindow, theEvent.where, &tempRect1);
- // ensure we are properly built
- if (BuildOffscreen (&gpGWOffScreen, gpWindow, &gwLocOffscreen))
- {
- FillOffscreen (gpGWOffScreen);
- BlitToWindow (gpGWOffScreen, gpWindow, &gwLocOffscreen);
- }
- break;
- case inGrow:
- SetRect (&rectGrow, 100, 100, 20000, 20000);
- grow = GrowWindow (whichWindow, theEvent.where, &rectGrow);
- if (grow)
- {
- SizeWindow (whichWindow, grow & 0x0000FFFF, grow >> 16, true);
- // ensure offscreen buffer is reallocated
- if (gpGWOffScreen)
- DisposeGWorld (gpGWOffScreen);
- gpGWOffScreen = NULL;
- AllocBuffer (gwLocOffscreen);
- //SetPort (whichWindow);
- SetPortWindowPort(whichWindow);
- //InvalRect (&whichWindow->portRect); // redraw all
- InvalWindowRect (whichWindow, &tempRect1);
- }
- break;
- case inSysWindow:
- //SystemClick(&theEvent, whichWindow);
- break;
- }
- break;
- case keyDown:
- case autoKey:
- theKey = theEvent.message & charCodeMask;
- theCode = (theEvent.message & keyCodeMask) >> 8;
- if ((theEvent.modifiers & cmdKey) != 0)
- {
- menuResult = MenuKey(theKey);
- if (HiWord(menuResult) != 0)
- DoMenu (menuResult);
- }
- else
- DoKey (theKey, theCode);
- break;
- case updateEvt:
- BeginUpdate((WindowPtr) theEvent.message);
- DoUpdate((WindowPtr) theEvent.message);
- EndUpdate((WindowPtr) theEvent.message);
- break;
- case diskEvt:
- break;
- case osEvt:
- break;
-
- case kHighLevelEvent:
- AEProcessAppleEvent(&theEvent);
- break;
-
- }
- }
- else
- {
- // idle tasks
- }
-
- DisposeRgn(rgnHandle);
- }
-
- // --------------------------------------------------------------------------
-
- void CleanUp (void)
- {
- MenuHandle hMenu;
-
- HideWindow (gpWindow);
- if (gpWindow)
- DisposeWindow (gpWindow);
- gpWindow = NULL;
-
- // this is VERY important since the GWorld may not be in the application heap zone
- // leaked memory here outside the app heap may not be recoverable without a restart
- if (gpGWOffScreen)
- DisposeGWorld (gpGWOffScreen);
- gpGWOffScreen = NULL;
-
- hMenu = GetMenuHandle (kMenuFile);
- DeleteMenu (kMenuFile);
- DisposeMenu (hMenu);
-
- hMenu = GetMenuHandle (kMenuApple);
- DeleteMenu (kMenuApple);
- DisposeMenu (hMenu);
- }
-
- // --------------------------------------------------------------------------
-
- int main (void)
- {
- if (SetUp ())
- while (!gDone)
- DoEvent ();
- CleanUp ();
- return 0;
- }
-
-
-